package edu.ilstu.mind.ise.ccp.logger.gui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.WindowEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;

public class TabbedLoggerGui extends JFrame {

	private static final long serialVersionUID = 1L;

	private static final String ERROR_TAB_NAME = "ERRORS";
	private final String[] priorityConsoles;
	
	private final JTabbedPane consoleTabs;
	private final Map<String, JConsoleArea> consoles = new HashMap<String, JConsoleArea>();
	private final Set<String> priorityConsoleNames = new HashSet<String>();
	private final SortedSet<String> nonPriorityConsoleNames = new TreeSet<String>();
	
	public TabbedLoggerGui(int width, int height) {
		this(width, height, false);
	}
	
	public TabbedLoggerGui(int width, int height, boolean systemExitOnClose) {
		this(width, height, systemExitOnClose, new String[0]);
	}
	
	public TabbedLoggerGui(int width, int height, boolean systemExitOnClose, String[] priorityConsoles) {
		setSize(width,height);
		if(systemExitOnClose) {
			setDefaultCloseOperation(EXIT_ON_CLOSE);
		} else {
			setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		}
		
		setTitle("ISE Logger");
		
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		consoleTabs = new JTabbedPane();
		add(consoleTabs, BorderLayout.CENTER);
		
		this.priorityConsoles = new String[priorityConsoles.length+1];
		this.priorityConsoles[0] = ERROR_TAB_NAME;
		for(int i = 0; i < priorityConsoles.length; i++) {
			this.priorityConsoles[i+1] = priorityConsoles[i];
		}
		
		getOrCreateConsoleTab(ERROR_TAB_NAME);
		
		setVisible(true);
	}
	
	@Override
	public void setVisible(boolean paramBoolean) {
		Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
		 
		int x = (screenSize.width-getSize().width)/2;
		int y = (screenSize.height-getSize().height)/2;
		setLocation(x, y);
		
		super.setVisible(paramBoolean);
	}
	
	public void close() {
		WindowEvent event = new WindowEvent(this, WindowEvent.WINDOW_CLOSING);
		Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(event);
	}
	
	public TextWriter getErrorTabWriter() {
		return consoles.get(ERROR_TAB_NAME);
	}
	
	public TextWriter getOrCreateConsoleTab(final String name) {
		JConsoleArea console = consoles.get(name);
		if(console == null) {
			console = new JConsoleArea();
			Panel panel = new Panel();
			panel.setLayout(new GridBagLayout());
			consoles.put(name, console);
			panel.add(console, createGridBagConstains(0, true));
			int pIdx = 0;
			for(pIdx = 0; pIdx < priorityConsoles.length; pIdx++) {
				if(priorityConsoles[pIdx].equals(name)) {
					break;
				}
			}
			if(pIdx == priorityConsoles.length) {
				// not a priority console: add after priority consoles
				// these are added alphabetically
				nonPriorityConsoleNames.add(name);
				int nonPriorityIdx = 0;
				Iterator<String> iter = nonPriorityConsoleNames.iterator();
				while(!iter.next().equals(name)) {
					nonPriorityIdx++;
				}
				int addIdx = priorityConsoleNames.size()+nonPriorityIdx;
				consoleTabs.add(panel, name, addIdx);
			} else {
				// priority console: find idx
				int idx=0;
				for(int i = 0; i < pIdx; i++) {
					if(consoles.containsKey(priorityConsoles[i])) {
						idx++;
					}
				}
				priorityConsoleNames.add(name);
				consoleTabs.add(panel, name, idx);
			}
		}
		return console;
	}	
	
	private GridBagConstraints createGridBagConstains(int y, boolean fill) {
		GridBagConstraints c = new GridBagConstraints();
		c.gridy=y;
		c.weighty=fill?1.0:0.0;
		c.weightx=fill?1.0:0.0;
		c.fill=fill?GridBagConstraints.BOTH:GridBagConstraints.NONE;
		return c;
	}

}

class JConsoleArea extends JScrollPane implements TextWriter {

	private static final long serialVersionUID = 5960614256514032936L;

	private final JTextArea textArea;
	
	public JConsoleArea() {
		super();
		this.textArea = new JTextArea();
		textArea.setEditable(false);
		setViewportView(textArea);
	}
	
	public void write(String text) {
		textArea.append(text);
	}
}
